Skip to content

Child-cluster Node API support#71

Merged
ebourgeois merged 1 commit into
mainfrom
nodes-api
May 30, 2026
Merged

Child-cluster Node API support#71
ebourgeois merged 1 commit into
mainfrom
nodes-api

Conversation

@ebourgeois

@ebourgeois ebourgeois commented May 30, 2026

Copy link
Copy Markdown
Collaborator

Routes Node/Pod operations to a CAPI/k0smotron workload (child) cluster while the ScheduledMachine lives on the management cluster.

  • New CRD field spec.kubeconfigSecretRef (src/crd.rs) — optional reference to a same-namespace -kubeconfig Secret; cross-namespace refs forbidden by design.

  • src/reconcilers/child_client.rs (+tests, ~1,400 lines) — resolves the right kube::Client (management vs child), caches by Secret with LRU + resourceVersion-based rotation.

  • src/reconcilers/child_watch.rs (+tests, untracked, ~520 lines) — one Node watcher per child cluster; maps child Node events back to ScheduledMachine reconciles via Controller::reconcile_on.

  • tests/integration_child_kubeconfig.rs (untracked, 416 lines) — end-to-end kubeconfig resolution tests.

  • Wiring/support: src/main.rs (controller plumbing), src/metrics.rs (Phase-2 child-cluster metrics), new error variants in the ScheduledMachine lives on the management cluster.

  • New CRD field spec.kubeconfigSecretRef (src/crd.rs) — optional reference to a same-namespace -kubeconfig Secret; cross-namespace refs resourceVersion-based rotation.

  • src/reconcilers/child_watch.rs (+tests, untracked, ~520 lines) — one Node watcher per child cluster; maps child Node events back to ScheduledMachine reconciles via Controller::reconcile_on.

  • tests/integration_child_kubeconfig.rs (untracked, 416 lines) — end-to-end kubeconfig resolution tests.

  • Wiring/support: src/main.rs (controller plumbing), src/metrics.rs (Phase-2 child-cluster metrics), new error variants in scheduled_machine.rs, Cargo.toml deps (kube unstable-runtime, tokio-stream, base64), and docs docs/src/concepts/child-cluster-kubeconfig.md + examples/scheduledmachine-child-cluster.yaml.

  1. Security hardening
  • RBAC validation of bootstrapSpec/infrastructureSpec — user anti-escalation via VAP authorizer rules (13a/13b) + controller-SA SelfSubjectAccessReview pre-flight (ensure_can_create()); new PermissionDenied error + metric.
  • Embedded metadata enforcement — loudly reject metadata.name/metadata.namespace (VAP rules 13c–13f + runtime validate_embedded_metadata()),
    while newly supporting metadata.labels/annotations (reserved-prefix-checked, controller labels win).
    Required making the embedded metadata preserve-unknown so the field isn't pruned before rejection.
  • Updated deploy/admission/validatingadmissionpolicy.yaml, regenerated CRD + api.md, threat-model (T1 hardened), admission-validation doc, and SCHEDULED_MACHINE_LABEL constant.

  • I have read the CONTRIBUTING.md file.
  • My commit messages are signed off with the Signed-off-by statement (use --signoff in the commit).

By submitting this pull request, I certify that I have read and agree to the terms of the Developer Certificate of Origin.

@ebourgeois ebourgeois force-pushed the nodes-api branch 2 times, most recently from b7ab45c to 9fcd72b Compare May 30, 2026 13:12
@ebourgeois ebourgeois changed the title 1. Child-cluster Node API support (the bulk of the branch) Child-cluster Node API support May 30, 2026
Comment thread .github/workflows/docs.yaml Fixed
Comment thread .github/workflows/docs.yaml Fixed
Comment thread .github/workflows/docs.yaml Fixed
Comment thread .github/workflows/docs.yaml Fixed
Routes Node/Pod operations to a CAPI/k0smotron workload (child) cluster while the ScheduledMachine lives on the management cluster.

- New CRD field spec.kubeconfigSecretRef (src/crd.rs)
— optional reference to a same-namespace <clusterName>-kubeconfig Secret; cross-namespace refs forbidden by design.
- src/reconcilers/child_client.rs (+tests, ~1,400 lines)
— resolves the right kube::Client (management vs child), caches by Secret with LRU + resourceVersion-based rotation.
- src/reconcilers/child_watch.rs (+tests, untracked, ~520 lines)
— one Node watcher per child cluster; maps child Node events back to ScheduledMachine reconciles via Controller::reconcile_on.
- tests/integration_child_kubeconfig.rs (untracked, 416 lines)
— end-to-end kubeconfig resolution tests.
- Wiring/support: src/main.rs (controller plumbing), src/metrics.rs (Phase-2 child-cluster metrics), new error variants in the ScheduledMachine lives on the management cluster.

- New CRD field spec.kubeconfigSecretRef (src/crd.rs)
— optional reference to a same-namespace <clusterName>-kubeconfig Secret; cross-namespace refs resourceVersion-based rotation.
- src/reconcilers/child_watch.rs (+tests, untracked, ~520 lines)
— one Node watcher per child cluster; maps child Node events back to ScheduledMachine reconciles via Controller::reconcile_on.
- tests/integration_child_kubeconfig.rs (untracked, 416 lines)
— end-to-end kubeconfig resolution tests.
- Wiring/support: src/main.rs (controller plumbing), src/metrics.rs (Phase-2 child-cluster metrics), new error variants in scheduled_machine.rs, Cargo.toml deps (kube unstable-runtime, tokio-stream, base64), and docs docs/src/concepts/child-cluster-kubeconfig.md + examples/scheduledmachine-child-cluster.yaml.

2. Security hardening

- RBAC validation of bootstrapSpec/infrastructureSpec
— user anti-escalation via VAP authorizer rules (13a/13b) + controller-SA SelfSubjectAccessReview pre-flight (ensure_can_create()); new PermissionDenied error + metric.
- Embedded metadata enforcement
— loudly reject metadata.name/metadata.namespace (VAP rules 13c–13f + runtime validate_embedded_metadata()),
  while newly supporting metadata.labels/annotations (reserved-prefix-checked, controller labels win).
  Required making the embedded metadata preserve-unknown so the field isn't pruned before rejection.
- Updated deploy/admission/validatingadmissionpolicy.yaml, regenerated CRD + api.md, threat-model (T1 hardened), admission-validation doc, and SCHEDULED_MACHINE_LABEL constant.

Signed-off-by: Erick Bourgeois <erick@jeb.ca>
@ebourgeois ebourgeois merged commit ba0c6ed into main May 30, 2026
43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants